package com.xbongbong.paas.help;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.AssembleModel;
import com.xbongbong.saas.model.BomBillModel;
import com.xbongbong.saas.model.ClueModel;
import com.xbongbong.saas.model.CommunicatePlanModel;
import com.xbongbong.saas.model.ContactModel;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.CostAdjustModel;
import com.xbongbong.saas.model.CreditLimitModel;
import com.xbongbong.saas.model.CreditTemporaryLimitModel;
import com.xbongbong.saas.model.CustomerCommunicateModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.CustomerStatementStatisticsModel;
import com.xbongbong.saas.model.InstockModel;
import com.xbongbong.saas.model.InventoryModel;
import com.xbongbong.saas.model.InvoiceModel;
import com.xbongbong.saas.model.MarketActivityModel;
import com.xbongbong.saas.model.OpportunityModel;
import com.xbongbong.saas.model.OutstockModel;
import com.xbongbong.saas.model.PaasFormDataModel;
import com.xbongbong.saas.model.PayPlanModel;
import com.xbongbong.saas.model.PayPlanSheetModel;
import com.xbongbong.saas.model.PaymentModel;
import com.xbongbong.saas.model.PaymentSheetModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductionOrderModel;
import com.xbongbong.saas.model.PurchaseInvoiceModel;
import com.xbongbong.saas.model.PurchaseModel;
import com.xbongbong.saas.model.QuotationModel;
import com.xbongbong.saas.model.RefundModel;
import com.xbongbong.saas.model.ReturnedPurchaseModel;
import com.xbongbong.saas.model.SupplierCommunicateModel;
import com.xbongbong.saas.model.SupplierContactModel;
import com.xbongbong.saas.model.SupplierModel;
import com.xbongbong.saas.model.TransferModel;
import com.xbongbong.saas.model.WarehouseModel;
import com.xbongbong.saas.model.WorkOrderModel;
import com.xbongbong.saas.model.WorkReportModel;
import com.xbongbong.saas.service.ScoreCalculateService;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.action.support.WriteRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 更新help
 * @author 魏荣杰
 * @date 2020/10/23 14:30
 * @since
 * @version
 */
@Component
public class ProUpdateHelp {
    private static final Logger LOG = LoggerFactory.getLogger(ProUpdateHelp.class);

    @Resource
    private CustomerModel customerModel;
    @Resource
    private ContactModel contactModel;
    @Resource
    private CustomerCommunicateModel customerCommunicateModel;
    @Resource
    private CommunicatePlanModel communicatePlanModel;
    @Resource
    private OpportunityModel opportunityModel;
    @Resource
    private ContractModel contractModel;
    @Resource
    private RefundModel refundModel;
    @Resource
    private QuotationModel quotationModel;
    @Resource
    private WorkReportModel workReportModel;
    @Resource
    private SupplierModel supplierModel;
    @Resource
    private SupplierContactModel supplierContactModel;
    @Resource
    private SupplierCommunicateModel supplierCommunicateModel;
    @Resource
    private PurchaseModel purchaseModel;
    @Resource
    private ReturnedPurchaseModel returnedPurchaseModel;
    @Resource
    private BomBillModel bomBillModel;
    @Resource
    private ProductionOrderModel productionOrderModel;
    @Resource
    private AssembleModel assembleModel;
    @Resource
    private InstockModel instockModel;
    @Resource
    private OutstockModel outstockModel;
    @Resource
    private InventoryModel inventoryModel;
    @Resource
    private TransferModel transferModel;
    @Resource
    private WarehouseModel warehouseModel;
    @Resource
    private PaymentModel paymentModel;
    @Resource
    private PayPlanModel payPlanModel;
    @Resource
    private InvoiceModel invoiceModel;
    @Resource
    private WorkOrderModel workOrderModel;
    @Resource
    private PaymentSheetModel paymentSheetModel;
    @Resource
    private PayPlanSheetModel payPlanSheetModel;
    @Resource
    private PurchaseInvoiceModel purchaseInvoiceModel;
    @Resource
    private ProductModel productModel;
    @Resource
    private ClueModel clueModel;
    @Resource
    @Lazy
    private ScoreCalculateService scoreCalculateService;
    @Resource
    private CreditLimitModel creditLimitModel;
    @Resource
    private CreditTemporaryLimitModel creditTemporaryLimitModel;
    @Resource
    private CustomerStatementStatisticsModel customerStatementStatisticsModel;
    @Resource
    private MarketActivityModel marketActivityModel;
    @Resource
    private CostAdjustModel costAdjustModel;
    @Resource
    private PaasFormDataModel paasFormDataModel;

    /**
     * Description: 更新
     * @param businessType
     * @param corpid
     * @param id
     * @param jsonObject data部分的数据
     * @return void
     * @throws
     * @author 魏荣杰
     * @date 2020/10/23 15:04
     * @since
     */
    public void update(Integer businessType, String corpid, Long id, JSONObject jsonObject) throws XbbException {
        if (Objects.isNull(businessType) || Objects.isNull(corpid) || Objects.isNull(id) || Objects.isNull(jsonObject)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        UpdateDataEntity updateData = ExplainUtil.getUpdateData(id, jsonObject, corpid);
        updateBatch(businessType, corpid, Collections.singletonList(updateData), true, WriteRequest.RefreshPolicy.WAIT_UNTIL);
    }

    public void update(Integer businessType, String corpid, Long id, String attr, Object value) throws XbbException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(attr, value);
        update(businessType, corpid, id, jsonObject);
    }

    public void updateByIds(Integer businessType, String corpid, List<Long> dataIds, String attr, Object value) throws XbbException {
        if (Objects.isNull(businessType) || Objects.isNull(corpid) || Objects.isNull(dataIds) || Objects.isNull(attr)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(attr, value);
        List<UpdateDataEntity> updateDataEntityList = new ArrayList<>();
        for (Long dataId : dataIds) {
            UpdateDataEntity updateData = ExplainUtil.getUpdateData(dataId, jsonObject, corpid);
            updateDataEntityList.add(updateData);
        }

        updateBatch(businessType, corpid, updateDataEntityList, true, WriteRequest.RefreshPolicy.WAIT_UNTIL);
    }

    public void updateByIds(Integer businessType, String corpid, List<Long> dataIds, JSONObject jsonObject) throws XbbException {
        if (Objects.isNull(businessType) || Objects.isNull(corpid) || Objects.isNull(dataIds) || Objects.isNull(jsonObject)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        List<UpdateDataEntity> updateDataEntityList = new ArrayList<>();
        for (Long dataId : dataIds) {
            UpdateDataEntity updateData = ExplainUtil.getUpdateData(dataId, jsonObject, corpid);
            updateDataEntityList.add(updateData);
        }
        updateBatch(businessType, corpid, updateDataEntityList, true, WriteRequest.RefreshPolicy.WAIT_UNTIL);
    }

    public void updateBatch(Integer saasMark, Integer businessType, String corpid, List<UpdateDataEntity> updateDataEntityList, Boolean updateScore, WriteRequest.RefreshPolicy refreshPolicy ) throws XbbException{
        if (Objects.equals(SaasMarkEnum.SAAS.getCode(), saasMark)) {
            updateBatch(businessType, corpid, updateDataEntityList, updateScore, refreshPolicy);
        } else {
            paasFormDataModel.updateBatch(updateDataEntityList, corpid, refreshPolicy);
        }
    }

    private void updateBatch(Integer businessType, String corpid, List<UpdateDataEntity> updateDataEntityList, boolean updateScore, WriteRequest.RefreshPolicy refreshPolicy) throws XbbException {
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        switch (xbbRefTypeEnum) {
            // CRM
            case CUSTOMER_MANAGEMENT:
                // 客户
                customerModel.updateBatch(updateDataEntityList, corpid, refreshPolicy);
                //评分更新（客户批量编辑，比如归档就会走这边）
                if(CollectionUtils.isNotEmpty(updateDataEntityList) && updateScore){
                    scoreCalculateService.asyncUpdateBatchDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT,corpid,updateDataEntityList.stream().map(item->item.getId()).collect(Collectors.toList()));
                }
                break;
            case CONTACT:
                // 联系人
                contactModel.updateBatch(updateDataEntityList, corpid);
                break;
            case CUSTOMER_COMMUNICATE:
                // 跟进记录
                customerCommunicateModel.updateBatch(updateDataEntityList, corpid);
                break;
            case COMMUNICATE_PLAN:
                // f访客计划
                communicatePlanModel.updateBatch(updateDataEntityList, corpid);
                break;
            case SALES_OPPORTUNITY:
                // 机会
                opportunityModel.updateBatch(updateDataEntityList, corpid, refreshPolicy);
                break;
            case CONTRACT:
                // 合同
                contractModel.updateBatch(updateDataEntityList, corpid, refreshPolicy);
                break;
            case REFUND:
                refundModel.updateBatch(updateDataEntityList, corpid);
                break;
            case WORK_REPORT:
            case WORKREPORT_WEEKLY:
            case WORKREPORT_DAILY:
            case WORKREPORT_MONTHLY:
                workReportModel.updateBatch(updateDataEntityList, corpid);
                break;
            case QUOTATION:
                quotationModel.updateBatch(updateDataEntityList, corpid);
                break;
            // 进销存
            case SUPPLIER:
                supplierModel.updateBatch(updateDataEntityList, corpid);
                break;
            case SUPPLIER_CONTACT:
                supplierContactModel.updateBatch(updateDataEntityList, corpid);
                break;
            case SUPPLIER_COMMUNICATE:
                supplierCommunicateModel.updateBatch(updateDataEntityList, corpid);
                break;
            case PURCHASE:
                purchaseModel.updateBatch(updateDataEntityList, corpid);
                break;
            case RETURNED_PURCHASE:
                returnedPurchaseModel.updateBatch(updateDataEntityList, corpid);
                break;
            case BOM_BILL:
                bomBillModel.updateBatch(updateDataEntityList, corpid);
                break;
            case PRODUCTION_ORDER:
                productionOrderModel.updateBatch(updateDataEntityList, corpid);
                break;
            case ASSEMBLE:
                assembleModel.updateBatch(updateDataEntityList, corpid);
                break;
            case INSTOCK:
            case PURCHASE_INSTOCK:
            case OTHER_INSTOCK:
            case REFUND_INSTOCK:
            case RETURNED_MATERIEL_INSTOCK:
            case PRODUCTION_INSTOCK:
                instockModel.updateBatch(updateDataEntityList, corpid);
                break;
            case OUTSTOCK:
            case CONTRACT_OUTSTOCK:
            case OTHER_OUTSTOCK:
            case RETURNED_PURCHASE_OUTSTOCK:
            case PRODUCTION_MATERIEL_OUTSTOCK:
            case WORK_ORDER_OUTSTOCK:
                outstockModel.updateBatch(updateDataEntityList, corpid);
                break;
            case INVENTORY:
                inventoryModel.updateBatch(updateDataEntityList, corpid);
                break;
            case TRANSFER:
                transferModel.updateBatch(updateDataEntityList, corpid);
                break;
            case WAREHOUSE:
                warehouseModel.updateBatch(updateDataEntityList, corpid);
                break;
            case PAYMENT:
                paymentModel.updateBatch(updateDataEntityList, corpid);
                break;
            case PAY_PLAN:
                payPlanModel.updateBatch(updateDataEntityList, corpid);
                break;
            case INVOICE:
                invoiceModel.updateBatch(updateDataEntityList, corpid);
                break;
            case WORK_ORDER:
                workOrderModel.updateBatch(updateDataEntityList, corpid);
                break;
            case PAYMENT_SHEET:
                paymentSheetModel.updateBatch(updateDataEntityList, corpid);
                break;
            case PAY_SHEET:
                payPlanSheetModel.updateBatch(updateDataEntityList, corpid);
                break;
            case PURCHASE_INVOICE:
                purchaseInvoiceModel.updateBatch(updateDataEntityList, corpid);
                break;
            case PRODUCT:
                productModel.updateBatch(updateDataEntityList, corpid);
                break;
            case CLUE:
                clueModel.updateBatch(updateDataEntityList, corpid, refreshPolicy);
                //评分更新（线索批量编辑， 比如归档就会走这边）
                if(CollectionUtils.isNotEmpty(updateDataEntityList) && updateScore){
                    scoreCalculateService.asyncUpdateBatchDataScore(XbbRefTypeEnum.CLUE,corpid,updateDataEntityList.stream().map(item->item.getId()).collect(Collectors.toList()));
                }
                break;
            case CREDIT_LIMIT:
                creditLimitModel.updateBatch(updateDataEntityList, corpid);
                break;
            case CREDIT_TEMPORARY_LIMIT:
                creditTemporaryLimitModel.updateBatch(updateDataEntityList, corpid);
                break;
            case CUSTOMER_STATEMENT_STATISTIC:
                customerStatementStatisticsModel.updateBatch(updateDataEntityList, corpid);
                break;
            case MARKET_ACTIVITY:
                marketActivityModel.updateBatch(updateDataEntityList, corpid);
                break;
            case COST_ADJUST:
                costAdjustModel.updateBatch(updateDataEntityList, corpid);
                break;
            default:
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * 根据key值改变对应的data的value值
     * 通过json_set语句实现，暂时只支持修改data下层的非对象和数组属性
     *
     * @param businessType 业务类型
     * @param corpid       公司id
     * @param refId        要修改的数据的id
     * @param attr         要修改的数据的attr
     * @param fieldType    要修改的数据的fieldType
     * @param value        要设置的值
     * @throws XbbException 类型转换失败异常
     * @author chaoxiong.lei
     * @Date 14:09 2019/1/23
     * @since v1.0
     **/
    public void jsonSetSetValueIntoFormDataById(Integer businessType, String corpid, Long refId, String attr, Integer fieldType, Object value) throws XbbException {
        if (businessType == null || corpid == null || refId == null || attr == null || fieldType == null || value == null) {
            return;
        }
        if (refId < 1) {
            // 要更改的数据不存在，直接返回
            return;
        }
        FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(fieldType);
        if (fieldTypeEnum == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
        }
        String esalias = fieldTypeEnum.getEsalias();
        String numEsAlias = FieldTypeEnum.NUM.getEsalias();
        String textEsAlias = FieldTypeEnum.TEXT.getEsalias();
        if (Objects.equals(esalias, numEsAlias)) {
            try {
                // TODO lcx 是否需要对原数据进行校验
                Number attrValue = (Number) value;
            } catch (Exception e) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
            }
        } else if (Objects.equals(esalias, textEsAlias)) {
            try {
                // TODO 怎么校验
                String attrValue = value.toString();
            } catch (Exception e) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
            }
        }

        update(businessType, corpid, refId, attr, value);
    }
    /**
     * saas paas 更新
     */
    public void updateBatch(Integer saasMark,Integer businessType, String corpid, List<UpdateDataEntity> updateDataEntityList) throws XbbException {
       if(Objects.equals(saasMark, SaasMarkEnum.PAAS.getCode())){
           paasFormDataModel.updateBatch(updateDataEntityList,corpid, WriteRequest.RefreshPolicy.NONE);
       }else {
           updateBatch(businessType,corpid,updateDataEntityList, false, WriteRequest.RefreshPolicy.NONE);
       }
    }
}
